package com.zerocarbon.framework.common.utils;

import cn.hutool.core.util.HexUtil;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

/**
 * Aes 加解密工具类
 *
 * @author yangtao
 * 2020年10月29日
 */
@Slf4j
public class AesUtil {

    private static final String CIPHER_INSTANCE = "AES/ECB/PKCS5Padding";
    private static final String AES_ALGORITHM = "AES";

    static {
        //AES/CBC/PKCS7Padding 依赖
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * AES加密
     * @param content
     * @param key
     * @return
     */
    public static byte[] aesEncrypt(byte[] content, String key) {	
    	return encrypt(content, key.getBytes(), "AES/CBC/PKCS7Padding", true, null);
    }

    /**
     * AES解密
     * @param key
     * @param input
     * @return
     * @throws Exception
     */
    public static byte[] aesDecrypt(byte[] content, String key) {
        return decrypt(content, key.getBytes(), "AES/CBC/PKCS7Padding", true, null);
    }

    /**
     * 加密
     *
     * @param content 待加密字符串
     * @param keyHex  aesKye的hexStr
     * @return
     */
    public static String encrypt(String content, String keyHex) {
        return HexUtil.encodeHexStr(encrypt(content.getBytes(), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null));
    }

    /**
     * 加密
     *
     * @param content 待加密字符串
     * @param key     密钥
     * @return
     */
    public static String encrypt(String content, byte[] key) {
        return HexUtil.encodeHexStr(encrypt(content.getBytes(), key, CIPHER_INSTANCE, false, null));
    }

    /**
     * 加密
     *
     * @param content 待加密字符串
     * @param keyHex  aesKye的hexStr
     * @return
     */
    public static byte[] encryptReturnByte(String content, String keyHex) {
        return encrypt(content.getBytes(), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null);
    }

    /**
     * 加密
     *
     * @param content 待加密字符串
     * @param key     密钥
     * @return
     */
    public static byte[] encryptReturnByte(String content, byte[] key) {
        return encrypt(content.getBytes(), key, CIPHER_INSTANCE, false, null);
    }

    /**
     * 加密
     *
     * @param content        待加密字符串
     * @param keyByte        aesKye的hexStr
     * @param cipherInstance AES算法填充方式
     * @param isIv           是否使用偏移量 ECB模式不可用
     * @param iv             偏移量 不传默认密钥
     * @return
     */
    public static byte[] encrypt(byte[] content, byte[] keyByte, String cipherInstance, Boolean isIv, byte[] iv) {
        try {
            //KEY转换
            Key key = new SecretKeySpec(keyByte, AES_ALGORITHM);
            //加密
            Cipher cipher = Cipher.getInstance(cipherInstance);
            if (isIv != null && isIv) {
                //偏移量 不传默认密钥
                if (iv == null) {
                    iv = keyByte;
                }
                IvParameterSpec ivps = new IvParameterSpec(iv);
                cipher.init(Cipher.ENCRYPT_MODE, key, ivps);
            } else {
                cipher.init(Cipher.ENCRYPT_MODE, key);
            }
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (NoSuchAlgorithmException e) {
        	log.error(e.getMessage(), e);
        } catch (InvalidKeyException e) {
        	log.error(e.getMessage(), e);
        } catch (NoSuchPaddingException e) {
        	log.error(e.getMessage(), e);
        } catch (BadPaddingException e) {
        	log.error(e.getMessage(), e);
        } catch (IllegalBlockSizeException e) {
        	log.error(e.getMessage(), e);
        } catch (InvalidAlgorithmParameterException e) {
        	log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 解密
     *
     * @param contentHex 待解密待字符串hexStr
     * @param keyHex     desKye的hexStr
     * @return
     */
    public static String decrypt(String contentHex, String keyHex) {
        return new String(decrypt(HexUtil.decodeHex(contentHex), HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null));
    }

    /**
     * 解密
     *
     * @param contentHex 待解密待字符串hexStr
     * @param key        密钥
     * @return
     */
    public static String decrypt(String contentHex, byte[] key) {
        return new String(decrypt(HexUtil.decodeHex(contentHex), key, CIPHER_INSTANCE, false, null));
    }

    /**
     * 解密
     *
     * @param content 待解密待内容
     * @param keyHex  密钥
     * @return
     */
    public static String decrypt(byte[] content, String keyHex) {
        return new String(decrypt(content, HexUtil.decodeHex(keyHex), CIPHER_INSTANCE, false, null));
    }

    /**
     * 解密
     *
     * @param content 待解密待内容
     * @param key     密钥
     * @return
     */
    public static String decrypt(byte[] content, byte[] key) {
        return new String(decrypt(content, key, CIPHER_INSTANCE, false, null));
    }


    /**
     * 解密
     *
     * @param contentByte    待解密待字符串hexStr
     * @param contentByte    密钥
     * @param cipherInstance AES算法填充方式
     * @param isIv           是否使用偏移量 ECB模式不可用
     * @param iv             偏移量 不传默认密钥
     * @return
     */
    public static byte[] decrypt(byte[] contentByte, byte[] keyByte, String cipherInstance, Boolean isIv, byte[] iv) {
        try {
            //KEY转换
            Key key = new SecretKeySpec(keyByte, AES_ALGORITHM);
            //解密
            Cipher cipher = Cipher.getInstance(cipherInstance);
            if (isIv != null && isIv) {
                //偏移量 不传默认密钥
                if (iv == null) {
                    iv = keyByte;
                }
                IvParameterSpec ivps = new IvParameterSpec(iv);
                cipher.init(Cipher.DECRYPT_MODE, key, ivps);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, key);
            }
            byte[] result = cipher.doFinal(contentByte);
            return result;
        } catch (NoSuchAlgorithmException e) {
        	log.error(e.getMessage(), e);
        } catch (InvalidKeyException e) {
        	log.error(e.getMessage(), e);
        } catch (NoSuchPaddingException e) {
        	log.error(e.getMessage(), e);
        } catch (BadPaddingException e) {
        	log.error(e.getMessage(), e);
        } catch (IllegalBlockSizeException e) {
        	log.error(e.getMessage(), e);
        } catch (InvalidAlgorithmParameterException e) {
        	log.error(e.getMessage(), e);
        }
        return null;
    }


//    public static void main(String[] args) {
//        jiemi();
//        //jiami();
//    }

//    public static void jiami(){
//        String key = "1f6714fc-fb9b-4a";
//        String content = "{\"id\":\"123\",\"time_stamp\":\"1603281282000\"}";
//        byte[] res = aesEncrypt(content.getBytes(),key);
//        System.out.println(HexUtil.encodeHexStr(res));
//    }
//
//    public static void jiemi(){
//        String hexStr = "a124dc15e00b1aef08bd37b51a6079f3c2f9cb5fc33d5bd22cfa0d894dc61a9fc936bacb65f852d638e81e9d6eb46001273beef9a64b97242d40cd5b34f2fb367591f8e91836cc83c967f26236b5f5eccd3366d01d8b7ebef4bdab4cf3b382ce302accd25096268819e0c4e1e8548a74bdb826ce177b6dc0a0f7b454c82d6c0dd31a18de25d97721e600388a66b5eccefb7c93bcce512050fe4580864b7bb52c18411a2fad77771c7c0b5306b5308b93b6ac3cab590cbb84eadb07138530ce83e341603db790bcacd822ae671c31b47ec611b1d966cd700b3efc8e4aae308078a2fd95ea1f3be6933818b4a497441e8d4ceb19b0898a418fad0114a854323f628889027d952c714541d689662a8396ee172960af98f07067301360a79ef6a0362ae4b35f2d0d6c3c1d9378aa4cfac7071d173178eb6366e50cd8a4d13da07ebd8c1a55a3a63decd7c4d2fe40b696deefed680258fd9c74313a563aad911a05a4a283d1868137710bc3b6bfa547a17922";
//        byte[] by = HexUtil.decodeHex(hexStr);
//        byte[] rs = aesDecrypt(by,"1f6714fc-fb9b-4a");
//        //System.out.println(HexUtil.encodeHexStr(rs));
//        System.out.println(new String(rs));
//    }

//    public static void main(String[] args) {
//        try {
//            //第一步： 生成KEY
//            //KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
//            //keyGenerator.init(256);
//            //第二步： 产生密钥
//            //SecretKey secretKey = keyGenerator.generateKey();
//            //第三步： 获取密钥
//            //byte[] keyBytes = secretKey.getEncoded();
//            //System.out.println(byteArrayToHexStr(keyBytes));
//            String src = "aaaaaaaaaVVVVaaaAAAA无";
//            String pwd = "41151AF257BFDB7859EEC62FB341EE95EE42E648FE24E1F8CE8DADE287CC1E5C";
//            String mw = encrypt(src,pwd);
//            System.out.println("mw:"+mw);
//            String jm = decrypt(mw,pwd);
//            System.out.println("jm:"+jm);
//
//        }catch (Exception e){
//
//        }
//
//    }
}
